<!DOCTYPE html>
<html lang="en">

<head><meta name="generator" content="Hexo 3.9.0">
	<!-- hexo-inject:begin --><!-- hexo-inject:end --><meta http-equiv="content-type" content="text/html; charset=utf-8">
	<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
	
	<!-- title -->
	
	<title>
	
		linux工具之sed | 
	 
	稻草人的编程之路
	</title>
	
	<!-- keywords,description -->
	 
		<meta name="description" content="人生的意义，不在于最终获得了什么，而在于曾经努力追求过什么">
	

	<!-- favicon -->
	
	<link rel="shortcut icon" href="/favicon.ico">
	
  

	<link rel="stylesheet" href="/css/main.css">
	<link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css">
	<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.17.1/build/styles/darcula.min.css">

	<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.17.1/build/highlight.min.js"></script>
	<script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js"></script>
	<script src="https://cdn.jsdelivr.net/npm/jquery-pjax@2.0.1/jquery.pjax.min.js"></script>
	<script src="/js/main.js"></script>
	
		<script src="https://cdn.jsdelivr.net/npm/leancloud-storage/dist/av-min.js"></script>
		<script src="https://cdn.jsdelivr.net/npm/valine@1.3.10/dist/Valine.min.js"></script>
	
	
		<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><!-- hexo-inject:begin --><!-- hexo-inject:end -->
	
</head>

<body>
	<!-- hexo-inject:begin --><!-- hexo-inject:end --><header id="header">
    <a id="title" href="/" class="logo">稻草人的编程之路</a>

	<ul id="menu">
		<li class="menu-item">
			<a href="/about" class="menu-item-link">ABOUT</a>
		</li>
		
		<li class="menu-item">
			<a href="https://github.com/wangxiaochuang" class="menu-item-link" target="_blank">
				<i class="fa fa-github fa-2x"></i>
			</a>
		</li>
	</ul>
</header>

	
<div id="sidebar">
	<button id="sidebar-toggle" class="toggle" ><i class="fa fa-arrow-right " aria-hidden="true"></i></button>
	
	<div id="site-toc">
		<input id="search-input" class="search-input" type="text" placeholder="search...">
		<div id="tree">
			

			
							<ul>
								<li class="directory">
									<a href="#" class="directory">
										<i class="fa fa-plus-square-o"></i>
										linux
									</a>
									
							<ul>
								<li class="directory">
									<a href="#" class="directory">
										<i class="fa fa-plus-square-o"></i>
										tools
									</a>
									
							<ul>
								<li class="file">
									<a href="/2019/08/18/100.html">
										awk
									</a>
								</li>
								<div class="article-toc" style="display: none;"></div>
							</ul>
			
							<ul>
								<li class="file">
									<a href="/2019/08/18/102.html">
										grep
									</a>
								</li>
								<div class="article-toc" style="display: none;"></div>
							</ul>
			
							<ul>
								<li class="file active">
									<a href="/2019/08/18/101.html">
										sed
									</a>
								</li>
								<div class="article-toc" style="display: none;"></div>
							</ul>
			
								</li>
								
							</ul>
			
								</li>
								
							</ul>
			
		</div>
	</div>
</div>

	<!-- 引入正文 -->
	<div id="content">
		<h1 id="article-title">

	sed
</h1>
<div class="article-meta">
	
	<span>wangxiaochuang</span>
	<span>2019-08-18 08:15:08</span>
    
		<div id="article-categories">
            
                
                    <span>
                        <i class="fa fa-folder" aria-hidden="true"></i>
                        <a href="/categories/linux/">linux</a>
						
							>
						
                    </span>
                
            
                
                    <span>
                        <i class="fa fa-folder" aria-hidden="true"></i>
                        <a href="/categories/linux/tools/">tools</a>
						
                    </span>
                
            
		</div>
    
</div>

<div id="article-content">
	<h1 id="sed"><a class="markdownIt-Anchor" href="#sed"></a> sed</h1>
<h2 id="基本用法"><a class="markdownIt-Anchor" href="#基本用法"></a> 基本用法</h2>
<p>有数据文件<code>data.txt</code>内容如下：</p>
<blockquote>
<p>1, jack, male, 28, beijing<br>
2, yuanyuan, female, 26, chongqing<br>
3, xiao, female, 26, sichuan<br>
4, straw, male, 25, shanghai<br>
5, lili, female, 23, chongqing</p>
</blockquote>
<p>看三个简单的例子理解sed的原理</p>
<p>例1：</p>
<pre class="highlight"><code class="sh">CMD:
  sed <span class="hljs-string">''</span> data.txt
OUTPUT:
  1, jack, male, 28, beijing
  2, yuanyuan, female, 26, chongqing
  3, xiao, female, 26, sichuan
  4, straw, male, 25, shanghai
  5, lili, female, 23, chongqing
</code></pre>
<p>例2：</p>
<pre class="highlight"><code class="sh">CMD:
  sed <span class="hljs-string">'2p'</span> data.txt
OUTPUT:
  1, jack, male, 28, beijing
  2, yuanyuan, female, 26, chongqing
  2, yuanyuan, female, 26, chongqing
  3, xiao, female, 26, sichuan
  4, straw, male, 25, shanghai
  5, lili, female, 23, chongqing
</code></pre>
<p>例3：</p>
<pre class="highlight"><code class="sh">CMD:
  sed <span class="hljs-string">'2d'</span> data.txt
OUTPUT:
  1, jack, male, 28, beijing
  3, xiao, female, 26, sichuan
  4, straw, male, 25, shanghai
  5, lili, female, 23, chongqing
</code></pre>
<p>可以简单归纳一下sed的命令格式：<code>awk [options] 'RANGE CMD' file</code></p>
<h3 id="sed工作原理"><a class="markdownIt-Anchor" href="#sed工作原理"></a> sed工作原理</h3>
<ol>
<li>读取文件的一行内容到其内存区，我们称为模式空间</li>
<li>判断该行内容是否属于待处理的范围内，如果不是进入第4步，如果是则进入第3步</li>
<li>执行sed命令</li>
<li>输出模式空间（-n选项控制，默认输出）继续回到第一步</li>
</ol>
<p>例1：由于没有任何sed命令，所以按行依次读入到模式空间后依次输出，所以得到文件内容</p>
<p>例2：这里的RANGE是2，表示第二行；要对属于RANGE的行执行sed命令<code>p</code>，即打印到标准输入；加上原本就应该输出模式空间的内容，所以就输出了两行第二行内容</p>
<p>例3：这里的RANGE是2，表示第二行；要对属于RANGE的行执行sed命令<code>d</code>，即删除该行；这时候模式空间就因这个命令给删除了，所以这一行就没有输出</p>
<p>那么像<code>p</code>和<code>d</code> 这样的命令还有什么呢？</p>
<table>
<thead>
<tr>
<th>sed命令</th>
<th>功能</th>
<th>示例</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td>向当前模式空间追加内容</td>
<td>sed ‘4a 4.5, xianxian, female, 28, beijing’ data.txt</td>
<td>如果是多行，添加换行符即可</td>
</tr>
<tr>
<td>i</td>
<td>与a命令一致，不同的是在模式空间前插入</td>
<td>sed ‘4i 3.5, …’ data.txt</td>
<td></td>
</tr>
<tr>
<td>d</td>
<td>删除当前模式空间内容</td>
<td>sed ‘2d’ data.txt</td>
<td></td>
</tr>
<tr>
<td>D</td>
<td>删除当前模式空间内容，直到遇到换行符为止</td>
<td></td>
<td></td>
</tr>
<tr>
<td>c</td>
<td>替换模式模块的内容</td>
<td>sed ‘3c 3.5, xianxian, female, 28, beijing’ data.txt</td>
<td></td>
</tr>
<tr>
<td>p</td>
<td>打印当前模式空间内容</td>
<td>sed ‘2p’ data.txt</td>
<td></td>
</tr>
<tr>
<td>P</td>
<td>打印当前模式空间内容直到遇到换行符为止</td>
<td></td>
<td></td>
</tr>
<tr>
<td>s</td>
<td>文本替换</td>
<td>sed ‘3s#i#I#g’ data.txt</td>
<td>将第三行的所有i替换为I，后面的g是标志，表示全部，否则只会替换第一个i</td>
</tr>
</tbody>
</table>
<h3 id="增删改查"><a class="markdownIt-Anchor" href="#增删改查"></a> 增删改查</h3>
<h4 id="添加内容"><a class="markdownIt-Anchor" href="#添加内容"></a> 添加内容</h4>
<p>在模式空间内容后添加内容</p>
<pre class="highlight"><code class="sh">CMD:
  sed <span class="hljs-string">'4a 4.5, xianxian, female, 28, beijing'</span> data.txt
OUTPUT:
  1, jack, male, 28, beijing
  2, yuanyuan, female, 26, chongqing
  3, xiao, female, 26, sichuan
  4, straw, male, 25, shanghai
  4.5, xianxian, female, 28, beijing
  5, lili, female, 23, chongqing
</code></pre>
<p>在模式空间内容前添加内容</p>
<pre class="highlight"><code class="sh">CMD:
  sed <span class="hljs-string">'4i 3.5, xianxian, female, 28, beijing'</span> data.txt
OUTPUT:
  1, jack, male, 28, beijing
  2, yuanyuan, female, 26, chongqing
  3, xiao, female, 26, sichuan
  3.5, xianxian, female, 28, beijing
  4, straw, male, 25, shanghai
  5, lili, female, 23, chongqing
</code></pre>
<h4 id="修改内容"><a class="markdownIt-Anchor" href="#修改内容"></a> 修改内容</h4>
<p>修改整个模式空间</p>
<pre class="highlight"><code class="sh">CMD:
  sed <span class="hljs-string">'3c 3.5, xianxian, female, 28, beijing'</span> data.txt
CMD:
  1, jack, male, 28, beijing
  2, yuanyuan, female, 26, chongqing
  3.5, xianxian, female, 28, beijing
  4, straw, male, 25, shanghai
  5, lili, female, 23, chongqing
</code></pre>
<h4 id="替换内容"><a class="markdownIt-Anchor" href="#替换内容"></a> 替换内容</h4>
<p>将模式空间中的所有小写i转成大写I，这里的#号可以换成任意的其他字符</p>
<pre class="highlight"><code class="sh">CMD:
  sed <span class="hljs-string">'3s#i#I#g'</span> data.txt
OUTPUT:
  1, jack, male, 28, beijing
  2, yuanyuan, female, 26, chongqing
  3, xIao, female, 26, sIchuan
  4, straw, male, 25, shanghai
  5, lili, female, 23, chongqing
</code></pre>
<p>替换的源头除了用字符串外，还可以是正则表达式（添加-r选项，表示使用扩展正则表达式，比如扩展正则表达式中括号不用反斜杠转义）；注意这里的<code>&amp;</code>符号表示匹配到的原始内容</p>
<pre class="highlight"><code class="sh">CMD:
  sed -r <span class="hljs-string">'3s#[0-9]+#(&amp;)#g'</span> data.txt
OUTPUT:
  1, jack, male, 28, beijing
  2, yuanyuan, female, 26, chongqing
  (3), xiao, female, (26), sichuan
  4, straw, male, 25, shanghai
  5, lili, female, 23, chongqing
</code></pre>
<p>加入想匹配模式空间中的所有内容，即整行</p>
<pre class="highlight"><code class>CMD:
  sed -r '3s#.*#(&amp;)#g' data.txt
OUTPUT:
  1, jack, male, 28, beijing
  2, yuanyuan, female, 26, chongqing
  (3, xiao, female, 26, sichuan)
  4, straw, male, 25, shanghai
  5, lili, female, 23, chongqing
</code></pre>
<p>也可以通过sed提取内容；通过这个命令我们可以发现，通过<code>\num</code>来使用正则表达式中引用</p>
<pre class="highlight"><code class>CMD:
  sed -r '3s#([0-9]+), (.*), (.*), ([0-9]+), (.*)#name: \2, age: \4#g' data.txt
OUTPUT:
  1, jack, male, 28, beijing
  2, yuanyuan, female, 26, chongqing
  name: xiao, age: 26
  4, straw, male, 25, shanghai
  5, lili, female, 23, chongqing
</code></pre>
<p>假如想要在行首或者行尾添加东西</p>
<pre class="highlight"><code class>CMD:
  sed '3s|^|# |g' data.txt
OUTPUT:
  1, jack, male, 28, beijing
  2, yuanyuan, female, 26, chongqing
  # 3, xiao, female, 26, sichuan
  4, straw, male, 25, shanghai
  5, lili, female, 23, chongqing
</code></pre>
<p>行尾使用<code>$</code></p>
<h3 id="关于range"><a class="markdownIt-Anchor" href="#关于range"></a> 关于RANGE</h3>
<p>前面的示例我们都只是演示了一种形式的RANGE，即行号；其实还有很多种其他的，见如下表</p>
<table>
<thead>
<tr>
<th>RANGE</th>
<th>功能</th>
<th>示例</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>不指定</td>
<td>sed ‘d’ data.txt</td>
<td>sed命令将作用于行，将删除每一行</td>
<td></td>
</tr>
<tr>
<td>2,4</td>
<td>指定2-4行</td>
<td>sed ‘2,4d’ data.txt</td>
<td>将对2、3、4行执行删除动作</td>
</tr>
<tr>
<td>2,+4</td>
<td>指定2到2+4行</td>
<td>sed ‘2,+4d’ data.txt</td>
<td>将对2、3、4、5、6行执行删除动作</td>
</tr>
<tr>
<td>2,$</td>
<td>指定2到最后一行</td>
<td>sed ‘2,$d’ data.txt</td>
<td>将对2到最后一行执行删除动作</td>
</tr>
<tr>
<td>1~2</td>
<td>从第一行开始递增2的行</td>
<td>sed ‘1~2d’ data.txt</td>
<td>对1、3、5行执行删除动作</td>
</tr>
<tr>
<td>/KEYWORD/</td>
<td>匹配到KEYWORD的行</td>
<td>sed ‘/xiao/d’ data.txt</td>
<td>删除匹配到单词xiao的这行</td>
</tr>
<tr>
<td>/KEYWORD1/,/KEYWORD2/</td>
<td>从匹配到KEYWORD1到KEYWORD2的行</td>
<td>sed ‘/xiao/,/lili/d’ data.txt</td>
<td>将对第3到5行执行删除动作</td>
</tr>
<tr>
<td>/KEYWORD/,3</td>
<td>匹配KEYWORD到第3行</td>
<td></td>
<td>如果前面3行没匹配到KEYWORD，就没有匹配的行</td>
</tr>
<tr>
<td>3,/KEYWORD/</td>
<td>匹配第3行到匹配到KEYWORD的行</td>
<td></td>
<td>如果第3行后没有匹配到KEYWORD，将默认匹配到最后一行</td>
</tr>
<tr>
<td>!</td>
<td>前面的返回取反</td>
<td>sed ‘2,4!d’ data.txt</td>
<td>除了2、3、4行外，执行删除</td>
</tr>
</tbody>
</table>
<h3 id="常用选项"><a class="markdownIt-Anchor" href="#常用选项"></a> 常用选项</h3>
<p>前面我们在工作原理那一节说过，sed会将处理过后的模式空间内容自动输出，有时间我们不需要这个功能，我们就可以使用<code>-n</code>禁止默认的模式空间输出，同样的还有其他的，见一下表：</p>
<table>
<thead>
<tr>
<th>sed选项</th>
<th>功能</th>
<th>示例</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>-n</code></td>
<td>禁止默认的模式空间打印</td>
<td><code>sed -n '3p' data.txt</code></td>
<td></td>
</tr>
<tr>
<td><code>-r</code></td>
<td>使用扩展的正则表达式</td>
<td><code>sed -r '3s#([0-9]+), (.*), (.*), ([0-9]+), (.*)#name: \2, age: \4#g' data.txt</code></td>
<td>如果不用该选项，这里的括号必须要转义</td>
</tr>
<tr>
<td><code>-e</code></td>
<td>可以接多个sed命令</td>
<td><code>sed -n -e '3d' -e '1p' data.txt</code></td>
<td>删除第三行，打印第一行；同<code>sed -n '3d;1p' data.txt</code></td>
</tr>
<tr>
<td><code>-i</code></td>
<td>使用模式空间的内容替换原内容</td>
<td><code>sed -i '3p' data.txt</code></td>
<td>data.txt文件的第三行将复制一行</td>
</tr>
</tbody>
</table>
<ol>
<li><code>-n</code>选项<br>
禁止默认的模式空间内容打印<pre class="highlight"><code class>CMD:
  sed -n '3p' data.txt
OUTPUT:
  3, xiao, female, 26, sichuan
</code></pre>
默认的输出禁止掉了，就只会打印这里指定打印的第三行</li>
<li><code>-e</code>选项<br>
执行多个sed命令<pre class="highlight"><code class>CMD:
  sed -n -e '3d' -e '1p' data.txt    # 同：sed -n '3d;1p' data.txt
OUTPUT:
  1, jack, male, 28, beijing
</code></pre>
</li>
</ol>
<h2 id="进阶用法"><a class="markdownIt-Anchor" href="#进阶用法"></a> 进阶用法</h2>
<h2 id="高级用法"><a class="markdownIt-Anchor" href="#高级用法"></a> 高级用法</h2>
<ol>
<li>
<p>高级sed命令<code>n</code>，提前读取下一行，覆盖当前模式空间<br>
覆盖前如果有默认输出，会先输出覆盖前的模式空间内容</p>
<pre class="highlight"><code class>CMD:
  sed 'n;p' data.txt
OUTPUT:
  1, jack, male, 28, beijing
  2, yuanyuan, female, 26, chongqing
  2, yuanyuan, female, 26, chongqing
  3, xiao, female, 26, sichuan
  4, straw, male, 25, shanghai
  4, straw, male, 25, shanghai
  5, lili, female, 23, chongqing
解释:
  读取第一行后，执行第一个命令n读入下一行，读入前会先输出模式空间内容，所以第一行打印了；执行n命令这时候读入的是第二行命令，执行p命令后，继续输出模式空间内容，所以第2行打印了两次；再读入下一行就是从第3行开始，因为第二行已经通过n命令读入了
如果取消默认输出
CMD:
  sed -n 'n;p' data.txt
OUTPUT:
  2, yuanyuan, female, 26, chongqing
  4, straw, male, 25, shanghai
解释：
  取消了默认的模式空间输出，就只是会输出p命令的打印内容，所以会输出偶数行
CMD:
  sed 'n;d' data.txt
OUTPUT:
  1, jack, male, 28, beijing
  3, xiao, female, 26, sichuan
  5, lili, female, 23, chongqing
解释：
  读取第一行后，执行sed命令n读入下一行，读入前先输出了模式空间内容，所以第一行打印了；n命令会读入第二行内容到模式空间，执行d命令后，模式空间内容清空了，所以没有输出的；继续读取第三行内容依次类推；通过这种方式输出基数行
CMD:
  sed -n '$!N;P' data.txt
OUTPUT:
  1, jack, male, 28, beijing
  3, xiao, female, 26, sichuan
  5, lili, female, 23, chongqing
解释：
  这里的P也是打印模式空间内容，只是它打印直到遇到换行符为止；前面的$!表示判断是否为最后一行，如果没有就会将最后一行忽略
</code></pre>
</li>
<li>
<p>高级sed命令<code>N</code>，提前读取下一行，追加到当前模式空间<br>
假设有如下数据</p>
<pre class="highlight"><code class>user1
pass1
user2
pass2
user3
pass3
user4
pass4
</code></pre>
<p>一个用户一个密码，依次按行放置，现在想将一个用户及其密码放到一行来</p>
<pre class="highlight"><code class>CMD:
  sed 'N;s#\n#=#g' new.txt
  sed -n 'N;s#\n#=#g;p' new.txt
OUTPUT:
  user1=pass1
  user2=pass2
  user3=pass3
  user4=pass4
解释：
  跟n一样也是提前读取下一行，但是会追加到当前模式空间，所以两行中间是有换行符的；再使用s命令将换行符换成=号
</code></pre>
</li>
</ol>
<h2 id="实例"><a class="markdownIt-Anchor" href="#实例"></a> 实例</h2>

</div>


    <div class="post-guide">
        <div class="item left">
            
        </div>
        <div class="item right">
            
              <a href="/2019/08/18/102.html">
                grep
                <i class="fa fa-angle-right" aria-hidden="true"></i>
              </a>
            
        </div>
    </div>




<script>
	
	
</script>
	</div>
	<div id="footer">
	<p>
	©2019-<span id="footerYear"></span> 
	<a href="/">wangxiaochuang</a> 
	
	
		|
		<span id="busuanzi_container_site_pv">
			pv
			<span id="busuanzi_value_site_pv"></span>
		</span>
		|
		<span id="busuanzi_container_site_uv"> 
			uv
			<span id="busuanzi_value_site_uv"></span>
		</span>
	
	</p>
</div>
<script type="text/javascript"> 
	document.getElementById('footerYear').innerHTML = new Date().getFullYear() + '';
</script>

	<button id="totop-toggle" class="toggle"><i class="fa fa-angle-double-up" aria-hidden="true"></i></button><!-- hexo-inject:begin --><!-- hexo-inject:end -->
</body>
</html>